package com.me.study;

import com.me.study.async.AsyncService;
import com.me.study.beanDefinitionRegistryPostProcessor.CustomBean;
import com.me.study.beanDefinitionRegistryPostProcessor.CustomBean2;
import com.me.study.config.AppConfig;
import com.me.study.config.MyPropertiesConfig;
import com.me.study.dao.IndexDao;
import com.me.study.dao.IndexDaoImpl1;
import com.me.study.dao.IndexDaoImpl2;
import com.me.study.event.HungerEvent;
import com.me.study.factoryBean.Car;
import com.me.study.factoryBean.TestFactoryBean;
import com.me.study.importSelector.ProductDaoImpl;
import com.me.study.service.IndexServiceImpl2;
import com.me.study.simpleMapperScan.UserDao;
import org.springframework.beans.BeansException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 *
 *
 * @author ME
 * @date   2019/12/14
 */
public class TestSpring {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		context.register(AppConfig.class);

		// Configuration类 有参构造注入: Configuration类 声明了有参构造后，spring 会根据参数自动注入 bean
		// context.register(AppConfig2.class);

		// context.register(AsyncConfig.class);// 异步调用配置类
		// context.register(IndexDaoImpl1.class);

		// 自定义 BeanFactoryPostProcessor 的方法二
		// context.addBeanFactoryPostProcessor(new TestBeanFactoryPostProcessor());

		context.refresh();
		System.out.println("\n=====================================");


		// 自定义 BeanDefinitionRegistryPostProcessor：
		// 借助 ClassPathBeanDefinitionScanner 扫描自定义注解 @CustomAnnotation
		CustomBean customBean = context.getBean(CustomBean.class);
		customBean.doSomething();
		try {
			CustomBean2 customBean2 = context.getBean(CustomBean2.class);
			customBean2.doSomething();
		} catch (BeansException e) {
			System.out.println("CustomBean2 没有标注 @CustomAnnotation，因此没有被识别为 Spring Bean\n");
		}


		// 自定义 BeanFactoryPostProcessor：此处使用方法一
		// 	方法一：TestBeanFactoryPostProcessor 配置注解 @Component,
		// 			对 IndexDao的 bean定义做了修改, 把 Scope 设为了原型, 所以两个对象不一样
		// 	方法二：不加 @Component 的话，可以自己添加进 spring容器 context.addBeanFactoryPostProcessor
		IndexDao indexDao = (IndexDao) context.getBean("indexDaoImpl1");
		System.out.println("233333 "+indexDao.getClass());
		indexDao.query();
		// IndexDao dao2 = context.getBean(IndexDao.class);
		// System.out.println("【Spring】 BeanFactoryPostProcessor: 从容器中取出两个 IndexDao, 对象是否相同: " + (dao.hashCode() == dao2.hashCode()));


		// 自定义 spring 事件
        context.publishEvent(new HungerEvent("Tom"));


		// 1，使用 TestImportBeanDefinitionRegistrar 注册 MyPropertiesConfig
		// 2，测试 PropertyPlaceholderConfigurer 能注入父类的属性
		MyPropertiesConfig propertiesConfig = context.getBean(MyPropertiesConfig.class);
		System.out.println("getStr: " + propertiesConfig.getStr() + "\n");


		// 使用 TestImportSelector 注册 ProductDaoImpl
		ProductDaoImpl productDao = context.getBean(ProductDaoImpl.class);
		productDao.list();


		// 使用 FactoryBean 获取 spring bean
		Car car = (Car) context.getBean("testFactoryBean");
		System.out.println("Car name: " + car.getName() + "\n");
		// System.out.println(car.hashCode() + " :: " + context.getBean("testFactoryBean").hashCode());


		// 获取 spring 工厂bean
		TestFactoryBean testFactoryBean = (TestFactoryBean) context.getBean("&testFactoryBean");
		System.out.println("FactoryBean className: " + testFactoryBean.getClass().getName() + "\n");


		// 异步调用，需解注 异步调用配置类
		AsyncService asyncService = context.getBean(AsyncService.class);
		asyncService.find();


		// Mybatis-MapperScan 的 基本原理：根据接口类型生成实现类，并纳入 spring 管理
		// 需要手动配置 MyImportBeanDefinitionRegistrar
		UserDao userDao = context.getBean(UserDao.class);
		userDao.getUser();


		System.out.println("indexDaoImpl2 hashCode1: " + context.getBean(IndexDaoImpl2.class).hashCode());
		System.out.println("IndexServiceImpl2.getDao() hashCode1: " + context.getBean(IndexServiceImpl2.class).getDao().hashCode() + "\n");
		// System.out.println("indexDaoImpl2 hashCode2: " + context.getBean(IndexDaoImpl2.class).hashCode());
		// System.out.println("IndexServiceImpl2.getDao() hashCode2: " + context.getBean(IndexServiceImpl2.class).getDao().hashCode());
	}
}
